// ArrowType.cpp : implementation file

/*
#ifndef _ARROWTYPE_CPP
#define _ARROWTYPE_CPP
*/
#include "stdafx.h"
#include "ArrowType.h"

/*
#ifndef _TYPE_CPP
#include "Type.cpp"
#endif
*/
Token::pointer ArrowType::applyArgument(Token::const_reference To)  const{
	if(To.isType( ))
		if(getLeft( ) == To)
			return getRight( ).clone( );

	throw Type::exception("Token::pointer ArrowType::applyArgument(Token::const_reference To) invalid argument");
}

ArrowType::ArrowType(const Type & L, const Type & R, const string& ss):
Type(ss), LeftRight(L, R){
		
}

ArrowType::ArrowType(const TokenPair& TP, const string& ss):
Type(ss), LeftRight(TP){
	if( TP.getLeft().isType() && TP.getRight().isType()) return;
	throw Type::exception("construction ArrowType::ArrowType(const TokenPair TP, string ss) wrong argument type");
}

ArrowType::ArrowType(const ArrowType& AT):Type(AT),LeftRight(AT.LeftRight){}
ArrowType::~ArrowType(){}

Token::pointer ArrowType::clone() const {
	return new ArrowType(*this);
	}

string ArrowType::view() const {
		return string("(")+getLeft().view()+"->"+getRight().view()+string(")");
	}
string ArrowType::toString() const {
	if (hasSyntax( )) return SyntacticSugar;
	return string("(")+getLeft().toString()+"->"+getRight().toString()+string(")");
	}

bool ArrowType::operator==(Token::const_reference To) const {
	if(To.isType()){
		Type::const_reference Ty = _TYPE(To);
		if(Ty.isArrowType()){
			const ArrowType& AT = _ARROWTYPE(Ty);
			return (LeftRight == AT.LeftRight);
			}
		}
	return false;
};

Token::pointer ArrowType::replaceAll(Token::const_reference To1, Token::const_reference To2) const{
	if(this->operator ==(To1)) return this->clone();	  	
	TokenPair* NewPair = LeftRight.replaceAll(To1, To2);
	Token::pointer Res = new ArrowType(*NewPair);
	delete NewPair;
	return Res;
}

size_t ArrowType::complexity() const{
	return this->LeftRight.complexity() + Type::complexity();
}

Type::const_reference ArrowType::FunctionTo() const{
	if(getRight().isArrowType())
		return _ARROWTYPE(getRight( )).FunctionTo();
	else
		return getRight();
	}

bool ArrowType::hasSubType(Type::const_reference Ty) const{
	return (getRight().hasSubType(Ty) || getLeft().hasSubType(Ty)) ;
	}
	
//#endif

